﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Xml;

namespace cellAnalysis
{
    public static class backprojection
    {
        private class histogram
        {
            public int m_bins;
            public int[] data;
            public int dataLength;
            //public int m_binIndex;

            public histogram(int bins, Bitmap Img)
            {
                m_bins = bins;
                data = new int[(int)Math.Pow(((double)256 / bins), 3)];
                dataLength = data.Length;
                fillHistoData(Img);
            }
            public int getBinIndex(Color pixelcolor, int val)
            {
                byte r, g, b;
                byte r_interval, g_interval, b_interval;

                r = pixelcolor.R;
                g = pixelcolor.G;
                b = pixelcolor.B;

                r_interval = (byte)((double)r / m_bins);
                g_interval = (byte)((double)g / m_bins);
                b_interval = (byte)((double)b / m_bins);

                
                //return (int)(b_interval + g_interval * (int)((double)256 / m_bins) + r_interval * Math.Pow(((int)((double)256 / m_bins)), 2));
                return (int)((b_interval + g_interval * val) + r_interval * Math.Pow(val, 2));
            }
            private void fillHistoData(Bitmap Img)
            {
                try
                {
                    int val = (int)((double)256 / m_bins);

                    for (int i = 0; i < Img.Height; i++)
                    {
                        for (int j = 0; j < Img.Width; j++)
                        {
                            data[getBinIndex(Img.GetPixel(j, i), val)]++;
                        }
                    }
                }
                catch(System.Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        public static void hist_backprojection(TImage SourceImg, TImage TemplateImg, TImage TargetImage, int bins)
        {
            byte bval;
            int i, j, id, val;
            double dval;

            try
            {
                
                histogram hist_Source = new histogram(bins, SourceImg.Image);

                histogram hist_Template = new histogram(bins, TemplateImg.Image);

                //String fileName = "\\values_Source.xml";
                //XmlDocument document = new XmlDocument();
                //XmlNode parametersNode = document.CreateElement("Values"); //Root - Element erzeugen
                //int counter = 0;
                //foreach (int wert in hist_Source.data) 
                //{

                //    XmlNode parameter = document.CreateElement(Convert.ToString(counter));
                //    counter++;
                //    XmlAttribute nameAttribute = document.CreateAttribute("Val");
                //    nameAttribute.Value = Convert.ToString(wert);
                //    parameter.Attributes.Append(nameAttribute);

                //    //parameter.InnerText = myParameter.Value;
                //    parametersNode.AppendChild(parameter);
                //}
                //document.AppendChild(parametersNode);

                //document.Save(Application.StartupPath+fileName);

                //counter = 0;

                //fileName = "\\values_Template.xml";
                //XmlDocument document2 = new XmlDocument();
                //XmlNode parametersNode2 = document2.CreateElement("Values"); //Root - Element erzeugen
                //foreach (int wert in hist_Template.data)
                //{
                //    XmlNode parameter2 = document2.CreateElement(Convert.ToString(counter));
                //    counter++;

                //    XmlAttribute nameAttribute2 = document2.CreateAttribute("Val");
                //    nameAttribute2.Value = Convert.ToString(wert);
                //    parameter2.Attributes.Append(nameAttribute2);

                //    //parameter.InnerText = myParameter.Value;
                //    parametersNode2.AppendChild(parameter2);
                //}
                //document2.AppendChild(parametersNode2);

                //document2.Save(Application.StartupPath + fileName);

                int value = (int)((double)256 / bins);

                for (i = 0; i < TargetImage.Height; i++)
                {
                    for (j = 0; j < TargetImage.Width; j++)
                    {
                        id = hist_Source.getBinIndex(SourceImg.GetRGBPixel(j, i), value);
                        if (hist_Template.data[id] > 0)
                        {
                            val = (int)(255 * ((double)hist_Source.data[id] / hist_Template.data[id]));
                            if (val > 255)
                                val = 255;
                        }
                        else
                            val = 0;
                        bval = (byte)val;
                        TargetImage.SetRGBPixel(j, i, Color.FromArgb(bval, bval, bval));
                    }
                    Application.DoEvents();
                    //dval = ((double)(j + i * j) / (TargetImage.Width * TargetImage.Height) * 100);
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        public static void multi_hist_backprojection(TImage SourceImg, List<TImage> TemplateImg, TImage TargetImage, int bins)
        {
            byte bval;
            int i, j, id, val;
            double dval;
            histogram hist_Source = null;
            histogram hist_Template = null;

            try
            {


                hist_Source = new histogram(bins, SourceImg.Image);
                //Bar_histo.Value = 25;

                int Count = TemplateImg.Count;

                for (int x = 0; x < Count; x++)
                {
                    hist_Template = new histogram(bins, TemplateImg[x].Image);
                    //Bar_histo.Value = 50 + (int)((((x + 1) / Count) * 50));
                    int value = (int)((double)256 / bins);
                    for (i = 0; i < TargetImage.Height; i++)
                    {
                        for (j = 0; j < TargetImage.Width; j++)
                        {
                            id = hist_Source.getBinIndex(SourceImg.GetRGBPixel(j, i), value);
                            if (hist_Template.data[id] > 0)
                            {
                                val = (int)(255 * ((double)hist_Source.data[id] / hist_Template.data[id]));
                                if (val > 255)
                                    val = 255;
                            }
                            else
                                val = 0;
                            bval = (byte)val;

                            if (val > TargetImage.GetPixel(j, i))
                            {
                                TargetImage.SetPixel(j, i, bval);
                            }
                        }
                        Application.DoEvents();
                        dval = ((((double)(j + i * j + x * TargetImage.Width * TargetImage.Height) / (TargetImage.Width * TargetImage.Height * Count) * 100)) / Count) * (x + 1);
                        //Bar_TargetImg.Value = (int)dval;
                    }

                    //Bar_histo.Value = 100;
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        //Histogram Backprojection mit mehreren Templates und Einfärbung der übereinstimmenden Pixel mit der im Template
        //eingestellten Klassifikationsfarbe
        public static void multi_hist_backprojection_classification(TImage SourceImg, List<TImage> TemplateImg, TImage TargetImage, int bins)
        {
            byte bval;
            int j, id, val;
            double dval;
            histogram hist_Source = null;
            histogram hist_Template = null;
            TImage backProjImage = new TImage(SourceImg.Width, SourceImg.Height, SourceImg.Pixelformat);

            try
            {

                hist_Source = new histogram(bins, SourceImg.Image);
                //Bar_histo.Value = 25;

                int Count = TemplateImg.Count;

                for (int x = 0; x < Count; x++)
                {
                    hist_Template = new histogram(bins, TemplateImg[x].Image);

                    int value = (int)((double)256 / bins);

                    for (int i = 0; i < TargetImage.Height; i++)
                    {
                        for (j = 0; j < TargetImage.Width; j++)
                        {
                            id = hist_Source.getBinIndex(SourceImg.GetRGBPixel(j, i), value);
                            if (hist_Template.data[id] > 0)
                            {
                                val = (int)(255 * ((double)hist_Source.data[id] / hist_Template.data[id]));
                                if (val > 255)
                                    val = 255;
                            }
                            else
                                val = 0;
                            bval = (byte)val;

                            if (val > backProjImage.GetPixel(j, i))
                            {
                                backProjImage.SetPixel(j, i, bval);
                                TargetImage.SetRGBPixel(j, i, TemplateImg[x].control.classificationColor);
                            }
                        }
                        Application.DoEvents();
                        dval = ((((double)(j + i * j + x * TargetImage.Width * TargetImage.Height) / (TargetImage.Width * TargetImage.Height * Count) * 100)) / Count) * (x + 1);
                    }
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

    }
}
